package sparrowGui.components
{
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.events.IEventDispatcher;
	
	import sparrowGui.components.item.STreeItem;
	import sparrowGui.components.item.TreeItemFactory;
	import sparrowGui.data.ListSelectionData;
	import sparrowGui.data.TreeComposite;
	import sparrowGui.data.TreeNodeVO;
	import sparrowGui.event.ItemEvent;
	import sparrowGui.event.ListEvent;
	import sparrowGui.i.IItem;
	import sparrowGui.i.ITreeItemFactory;
	import sparrowGui.i.ITreeNode;
	
	/** 项数据更新. **/
	[Event(name="list_item_update", 	type="sparrowGui.event.ListEvent")]
	/** 项选中状态改变. **/
	[Event(name="list_item_select", 	type="sparrowGui.event.ListEvent")]
	/** 项可折叠. **/
	[Event(name="list_item_fold", 	type="sparrowGui.event.ListEvent")]
	
	/**
	 * 树形组件,仿资源管理器
	 * 收缩会取消选择所有项
	 * 
	 * <tree>
	 * 		<node nodeId='' pid='' skinCls='' txtName='' selected='' />
	 * 		<node nodeId='' pid='' skinCls='' txtName='' selected='' />
	 * </tree>
	 * 
	 * 还缺少键盘上下事件未实现
	 * 
	 * @author Pelephone
	 * @website http://cnblogs.com/pelephone
	 */
	public class STree extends BaseUIComponent
	{
		// 项命令前缀,用"$"分隔是因为$在flash cs里面可给变量命名
		private static const ITEM_SKIN_PREFIX_NAME:String = "child$";
		
		// 根节点id
		private static const ROOT_ID:int = 0;
		
		// 对应数据
		private var dataIdHm:Object;	//<int,ITreeNode>
		
		private var _data:Object;
		private var treeNodes:TreeComposite;
		
		/**
		 * 项哈希<int,IItem>
		 */
		private var itemTarget:Object;
		/**
		 * 项列表，排列用
		 
		private var itemLs:Vector.<IItem>;*/
		
		/**
		 * 排列时暂存Y坐标
		 */
		private var tmpY:int;
		
		/**
		 * 选中数据
		 */
		private var selectData:ListSelectionData;
		/**
		 * 项生成工厂
		 */
		private var itemFactory:ITreeItemFactory;
		
		/**
		 * 选中项
		 */
		private var selectIndex:int = -1;
		private var _indent:int = 10;
		private var _colNum:int = 1;
		private var _colWidth:int;
		private var _rowHeight:int;
		private var _spacing:int = 2;
		
		/**
		 * 初始树形组件
		 * @param argSkin
		 * @param parentItemSkinCls		父节点项皮肤
		 * @param childItemSkinCls		子节点项皮肤
		 */
		public function STree(uiVars:Object=null,cellFactory:ITreeItemFactory=null)
		{
			itemTarget = {};
			
			this.itemFactory = cellFactory || new TreeItemFactory(STreeItem,"treeItem","richItem");
			selectData = new ListSelectionData();
			
			super(uiVars);
		}
		
		/**
		 * 通过xml更新本控件
		 * @param o
		 */
		public function update(o:Object):void
		{
			if(o is Vector.<ITreeNode>)
			{
				updateByVOLs(o as Vector.<ITreeNode>);
				return;
			}
			_data = 0;
			if(o==null) return;
			var nodeLs:Vector.<ITreeNode> = new Vector.<ITreeNode>();
			for each(var childXml:XML in o.children())
			{
				if(childXml) childXml = childXml[0];		// 调整到子结点
				if(o==null || !XML(childXml).length()) continue;
				
				var nodeVO:ITreeNode = newTreeNode();
				nodeVO.pid = childXml.attribute("pid");
				nodeVO.txtName = childXml.attribute("txtName");
				nodeVO.nodeId = childXml.attribute("nodeId");
				nodeVO.skinCls = childXml.attribute("skinCls");
				nodeVO.folded = childXml.attribute("folded");

				nodeLs.push(nodeVO); 
			}
			freshByLs(nodeLs);
		}
		
		/**
		 * 通过特定的vo数组更新数据
		 * @param arr
		 */
		public function updateByVOLs(nodeLs:Vector.<ITreeNode>):void
		{
			_data = nodeLs;
			
			freshByLs(nodeLs);
		}
		
		private function freshByLs(nodeLs:Vector.<ITreeNode>):void
		{
			dataIdHm = {};
			dataIdHm[ROOT_ID] = new TreeComposite(ROOT_ID);
			
			for each (var childVO:ITreeNode in nodeLs) 
			{
				if(!dataIdHm[childVO.pid])
					dataIdHm[childVO.pid] = new TreeComposite(childVO.pid);
				
				var parentNode:TreeComposite = dataIdHm[childVO.pid] as TreeComposite;
				
				if(!dataIdHm[childVO.nodeId])
					dataIdHm[childVO.nodeId] = new TreeComposite(childVO.nodeId);
				
				var treeNode:TreeComposite = dataIdHm[childVO.nodeId] as TreeComposite;
				treeNode.data = childVO;
				parentNode.add(treeNode);
			}
			
			treeNodes = dataIdHm[ROOT_ID] as TreeComposite;
			
			removeAllItems();
			createItemRecursive(treeNodes);
			addSkinListen();
			arrangeItems();
		}
		
		/**
		 * 添加单选事件
		 */
		override protected function addSkinListen():void
		{
			for each (var itm:IEventDispatcher in itemTarget) 
			{
				itm.addEventListener(ItemEvent.ITEM_FOLD_CHANGE,onItemFoldEvt);
				itm.addEventListener(ItemEvent.ITEM_SELECT_CHANGE,onItemSelectEvt);
			}
		}
		
		/**
		 * 移出项事件
		 */
		override protected function removeSkinListen():void
		{
			for each (var itm:IEventDispatcher in itemTarget) 
			{
				itm.removeEventListener(ItemEvent.ITEM_FOLD_CHANGE,onItemFoldEvt);
				itm.removeEventListener(ItemEvent.ITEM_SELECT_CHANGE,onItemSelectEvt);
			}
		}
		
		
		/**
		 * 合起事件
		 * @param e
		 */
		private function onItemFoldEvt(e:ItemEvent):void
		{
			var nodeId:int = getNodeIdByName(e.currentTarget.name);
			var trc:TreeComposite = getComposite(nodeId);
			trc.folded = !trc.folded;
			getItemById(nodeId).setState(STreeItem.FOLDSTATE_NAME,trc.folded);
			
			// 子项反选
			for (var i:int = 0; i < trc.numChildren; i++) 
			{
				var ctr:TreeComposite = trc.getChildById(i);
				getItemById(ctr.id).setState(STreeItem.SELECTSTATE_NAME,false);
				selectData.removeSelect(ctr.id);
			}
			var isSelect:Boolean = selectData.isSelect(nodeId);
			if(!isSelect)
				selectData.setSelect(nodeId);
			
			arrangeItems();
			
			dispatchEvent(new ListEvent(ListEvent.LIST_ITEM_FOLD));
		}
		
		/**
		 * 选中状态改变,不监听item的选中改变是因为会跟子项反选处理冲突
		 * @param e
		 */
		private function onItemSelectEvt(e:ItemEvent):void
		{
			var nodeId:int = getNodeIdByName(e.currentTarget.name);
//			var c:TreeComposite = getComposite(nodeId);
//			c.selected = !c.selected;
//			getItemById(nodeId).setState(TreeItem.SELECTSTATE_NAME,c.selected);
			
			selectData.setSelect(nodeId);
			
			arrangeItems();
		}
		
		/**
		 * 更新子项数据
		 * @param itm
		 * @param data
		 */
		protected function updateItem(itm:IItem,data:ITreeNode=null):void
		{
			itm.update(data);
			dispatchEvent(new ListEvent(ListEvent.LIST_ITEM_UPDATE,data,itm));
		}
		
		/**
		 * 新建节点数据
		 * @return 
		 */
		protected function newTreeNode():ITreeNode
		{
			return new TreeNodeVO();
		}
		
		/**
		 * 创建项
		 * @param nodeVO
		 */
		protected function createItem(nodeCps:TreeComposite):IItem
		{
			var nodeVO:ITreeNode = nodeCps.data;
			// 父元素不生成项
			if(!nodeVO || nodeVO.nodeId==ROOT_ID) return null;
			
			if(nodeVO.skinCls==null){
				var itm:IItem = newChildItem(nodeVO.skinCls);
			}
			// 有子节点项并且父项不是根
			else if(nodeVO.pid==ROOT_ID || nodeCps.numChildren>0)
				itm = newParentItem();
			else
				itm = newChildItem();
			
			itm.name = ITEM_SKIN_PREFIX_NAME + nodeVO.nodeId;
			return itm;
		}
		
		/**
		 * 新建父项
		 * @return 
		 */
		protected function newParentItem():IItem
		{
			return itemFactory.createNewItem(newParentItemSkin());
		}
		/**
		 * 新建父项皮肤
		 * @return 
		 */
		protected function newParentItemSkin():DisplayObject
		{
			return itemFactory.createNewItemSkin();
		}
		
		/**
		 * 新建子项
		 * @return 
		 */
		protected function newChildItem(uiVars:Object=null):IItem
		{
			uiVars = uiVars || newChildItemSkin();
			return itemFactory.createNewChildItem(uiVars);
		}
		/**
		 * 新建子项皮肤
		 * @return 
		 */
		protected function newChildItemSkin():DisplayObject
		{
			return itemFactory.createNewChildItemSkin();
		}
		
		/**
		 * 递归创建项
		 * @param nodeVO 节点数据
		 * @param posY   项y坐标
		 */
		private function createItemRecursive(nodeCps:TreeComposite):IItem
		{
			var itm:IItem = createItem(nodeCps);
			// 根节点不生成项
			if(itm){
				updateItem(itm,nodeCps.data);
				
//				skinDC.addChild(itm.skin);
				itemTarget[nodeCps.data.nodeId] = itm;
				
				if(!nodeCps.parent || !nodeCps.parent.folded)
				{
					itm.skin.x = (nodeCps.depth-1) * indent;
					tmpY = tmpY + (spacing + (rowHeight?rowHeight:itm.skin.height));
					itm.skin.y = tmpY;
				}
			}
			
			for (var i:int = 0; i < nodeCps.numChildren; i++) 
			{
				var childCps:TreeComposite = nodeCps.getChildById(i);
				var childItm:IItem = createItemRecursive(childCps);
			}
			return itm;
		}
		
		/**
		 * 排列所有项
		 */
		public function arrangeItems():void
		{
			tmpY = 0;
			arrangeRecursive(treeNodes);
		}
		
		
		/**
		 * 递归排列
		 * @param nodeCps
		 * @return 
		 */
		private function arrangeRecursive(nodeCps:TreeComposite):IItem
		{
			var itm:IItem = getItemByNodeId(nodeCps.id);
			// 根节，或者父类是合起的就不添加
			if(itm && (!nodeCps.parent || !nodeCps.parent.folded)){
				itm.skin.x = (nodeCps.depth-1) * indent;
				itm.skin.y = tmpY;
				tmpY = tmpY + (spacing + (rowHeight?rowHeight:itm.skin.height));
				skinDC.addChild(itm.skin);
				
				var itmSelected:Boolean = selectData.isSelect(nodeCps.id);
				itm.setState(STreeItem.SELECTSTATE_NAME,itmSelected);
			}
				
			if(itm && nodeCps.parent.folded && itm.skin.parent)
				skinDC.removeChild(itm.skin);
			
			for (var i:int = 0; i < nodeCps.numChildren; i++) 
			{
				var childCps:TreeComposite = nodeCps.getChildById(i);
				var childItm:IItem = arrangeRecursive(childCps);
			}
			return itm;
		}
		
		/**
		 * 移除所有项
		 */
		public function removeAllItems():void
		{
			removeSkinListen();
			
			for each (var itm:IItem in itemTarget) 
			{
				itemFactory.disposeItemSkin(itm.skin);
				itemFactory.disposeItem(itm);
			}
//			itemLs = new Vector.<IItem>();
			itemTarget = {};
		}
		
		////////////////////////////////////////////
		// get/set
		////////////////////////////////////////////
		
		/**
		 * 获取组合信息
		 * @param nodeId
		 */
		private function getComposite(nodeId:int):TreeComposite
		{
			return dataIdHm[nodeId] as TreeComposite;
		}
		
		/**
		 * 通过子项id获取节点数据对象
		 * @param childId 节点id,一般0是根节点
		 * @return 
		 */
		public function getItemById(nodeId:int):IItem
		{
			return itemTarget[nodeId];
		}
		
		/**
		 * 通过节点皮肤获取节点对象的数据
		 * @param skinName
		 * @return 
		 */
		private function getItemByName(itmName:String):IItem
		{
			var nodeId:int = getNodeIdByName(itmName);
			return getItemById(nodeId);
		}
		
		/**
		 * 通过基名获取id
		 * @param itmName
		 */
		private function getNodeIdByName(itmName:String):int
		{
			return int(itmName.replace(ITEM_SKIN_PREFIX_NAME,""));
		}
		
		/**
		 * 通过节点获取节点对象的项控制类
		 * @param nodeId
		 * @return 
		 */
		public function getItemByNodeId(nodeId:int):IItem
		{
			return itemTarget[nodeId] as IItem;
		}
		
		private function get skinDC():DisplayObjectContainer
		{
			return skin as DisplayObjectContainer;
		}
		
		override public function getDefaultUIName():String
		{
			return "tree";
		}

		/**
		 * 每项间隔
		 */
		public function get spacing():int
		{
			return _spacing;
		}

		/**
		 * @private
		 */
		public function set spacing(value:int):void
		{
			_spacing = value;
		}
		
		/**
		 * 每行有的列数,如列表组件一般是每行1列
		 */
		public function get colNum():int
		{
			return _colNum;
		}
		
		/**
		 * @private
		 */
		public function set colNum(value:int):void
		{
			_colNum = value;
		}
		
		/**
		 * 列宽
		 */
		public function get colWidth():int
		{
			return _colWidth;
		}
		
		/**
		 * @private
		 */
		public function set colWidth(value:int):void
		{
			_colWidth = value;
		}
		
		/**
		 * 行高
		 */
		public function get rowHeight():int
		{
			return _rowHeight;
		}
		
		/**
		 * @private
		 */
		public function set rowHeight(value:int):void
		{
			_rowHeight = value;
		}

		/**
		 * 缩进
		 */
		public function get indent():int
		{
			return _indent;
		}

		/**
		 * @private
		 */
		public function set indent(value:int):void
		{
			_indent = value;
		}
		
		public function get selectNodeId():int 
		{
			return selectData.getSelectIndex();
		}
		
		public function get selectItem():IItem
		{
			return getItemById(selectNodeId);
		}
	}
}